package com.atguigu.spzx.product.service.impl;

import com.alibaba.fastjson.JSON;
import com.atguigu.spzx.common.annotation.GuiguCache;
import com.atguigu.spzx.common.constant.RedisConst;
import com.atguigu.spzx.model.entity.product.Category;
import com.atguigu.spzx.product.mapper.CategoryMapper;
import com.atguigu.spzx.product.service.CategoryService;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.cache.annotation.Cacheable;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.CollectionUtils;
import org.springframework.util.StringUtils;

import java.util.List;
import java.util.concurrent.TimeUnit;
import java.util.stream.Collectors;

@Service
@Transactional
@Slf4j
public class CategoryServiceImpl implements CategoryService {

    @Autowired
    CategoryMapper categoryMapper;

    @Autowired
    RedisTemplate<String, String> redisTemplate;

    //经常被查询，不经常修改的数据适合存放到Redis缓存中，提高效率。
//    @Override
//    public List<Category> findOneCategory() {
//        //1.先查询缓存，缓存有直接返回
//        String oneCategoryListJson = redisTemplate.opsForValue().get("category:one");
//        if (StringUtils.hasText(oneCategoryListJson)) {
//            List<Category> oneCategoryList = JSON.parseArray(oneCategoryListJson, Category.class);
//            log.info("从Redis获取一级分类数据：" + oneCategoryList);
//            return oneCategoryList;
//        }
//        //2.缓存没有，再查询数据库，并放在缓存中，下次可以利用缓存，提高效率
//        List<Category> oneCategoryList = categoryMapper.findOneCategory();
//        redisTemplate.opsForValue().set("category:one", JSON.toJSONString(oneCategoryList), 7, TimeUnit.DAYS);
//        log.info("从MySQL获取一级分类数据：" + oneCategoryList);
//        return oneCategoryList;
//    }

    //没有集成Redis，每次查询数据都走数据库，效率低
    //@Cacheable(value = "categroyList",key = "'one'")

    @GuiguCache(
            cacheKey = RedisConst.CATEGORY_ONE,
            enableLock = true ,
            lockName = RedisConst.CATEGORY_ONE_LOCK
    )
    @Override
    public List<Category> findOneCategory() {
        return categoryMapper.findOneCategory();
    }

    @Cacheable(value = "categroyTree",key = "'all'")
    @Override
    public List<Category> findCategoryTree() {
        //1.查询所有分类列表
        List<Category> categoryList = categoryMapper.findAll(); //703条

        //2.组装父子关系
        List<Category> oneCategoryList = categoryList.stream()
                .filter(category -> category.getParentId().longValue() == 0).collect(Collectors.toList());

        if (!CollectionUtils.isEmpty(oneCategoryList)) {
            //组装一级分类和二级分类的父子关系
            //对一级分类进行迭代，去组装每一个一级分类所对应二级分类
            oneCategoryList.forEach(oneCategory -> {
                List<Category> twoCategoryList = categoryList.stream()
                        .filter(category -> category.getParentId().longValue() == oneCategory.getId().longValue()).collect(Collectors.toList());
                oneCategory.setChildren(twoCategoryList);

                if (!CollectionUtils.isEmpty(twoCategoryList)) {
                    //组装二级分类和三级分类的父子关系
                    //对二级分类进行迭代，去组装每一个二级分类所对应三级分类
                    twoCategoryList.forEach(twoCategory -> {
                        List<Category> threeCategoryList = categoryList.stream()
                                .filter(category -> category.getParentId().longValue() == twoCategory.getId().longValue()).collect(Collectors.toList());
                        twoCategory.setChildren(threeCategoryList);
                    });
                }
            });
        }

        //3.返回一级分类列表即可。二级分类、三级分类都封装在children属性上
        return oneCategoryList;
    }
}
